<template>
  <n-modal v-model:show="show"
           class="max-w-xl "
           :mask-closable="false"
           preset="card"
           @before-hide="modalClose"
           :bordered="false">
    <n-tabs class="mb-3"
            :default-value="tab"
            size="large"
            animated
            @before-leave="tabBeforeLeave"
            @update:value="tabUpdate"
            justify-content="space-evenly">
      <n-tab :disabled="mode==='edit'&&tab!=='string'" name="string" tab="string">
      </n-tab>
      <n-tab :disabled="mode==='edit'&&tab!=='set'" name="set" tab="set">
      </n-tab>
      <n-tab :disabled="mode==='edit'&&tab!=='list'" name="list" tab="list">
      </n-tab>
      <n-tab :disabled="mode==='edit'&&tab!=='zset'" name="zset" tab="zset">
      </n-tab>
      <n-tab :disabled="mode==='edit'&&tab!=='hash'" name="hash" tab="hash">
      </n-tab>
    </n-tabs>
    <div>
      <n-form ref="formRef" label-placement="left" label-width="80" :model="form" :rules="rules" class="px-5">
        <n-form-item path="key" label="键">
          <n-input :disabled="mode==='edit'" :loading="keyInputLoading" v-model:value="form.key" placeholder="请输入键"
                   size="large"
                   @input="onKeyInput">
            <template #suffix>
              <div v-if="hasKey" class="text-sm text-red-500">该键已存在</div>
            </template>
          </n-input>
        </n-form-item>
        <n-form-item path="expire" label="过期时间">
          <n-input v-model:value="form.expire" placeholder="过期时间/秒(不填则无期限)">
            <template #suffix>秒</template>
          </n-input>
        </n-form-item>
        <div v-if="tab==='string'">
          <n-form-item path="data[0].value" :rule="emptyRule" label="值">
            <n-input v-model:value="form.data[0].value" placeholder="请输入值" size="large"></n-input>
          </n-form-item>
        </div>
        <!--        <n-form-item v-if="tab==='zset'" path="score" label="分值">-->
        <!--          <n-input v-model:value="form.score" placeholder="请输入分值" size="large"></n-input>-->
        <!--        </n-form-item>-->
        <div v-else-if="tab==='zset'">
          <n-dynamic-input
              v-model:value="form.data"
              :on-create="onCreate"
              :min="1"
              #="{ index }">
            <n-form-item
                :label="`分值${index+1}`"
                :rule="emptyRule"
                :path="`data[${index}].value`">
              <n-input
                  v-model:value="form.data[index].score"
                  placeholder="请输入分值"
                  @keydown.enter.prevent/>
            </n-form-item>
            <n-form-item
                :label="`值${index+1}`"
                :rule="emptyRule"
                :path="`data[${index}].value`">
              <n-input
                  v-model:value="form.data[index].value"
                  placeholder="请输入值"
                  @keydown.enter.prevent/>
            </n-form-item>
          </n-dynamic-input>
        </div>
        <!--        <n-form-item v-if="tab==='hash'" path="hashKey" label="hash">-->
        <!--          <n-input v-model:value="form.hashKey" placeholder="请输入Hash键" size="large"></n-input>-->
        <!--        </n-form-item>-->
        <div v-else-if="tab==='hash'">
          <n-dynamic-input
              v-model:value="form.data"
              :on-create="onCreate"
              :min="1"
              #="{ index }">
            <n-form-item
                :label="`Hash键${index+1}`"
                :rule="emptyRule"
                :path="`data[${index}].value`">
              <n-input
                  v-model:value="form.data[index].hashKey"
                  placeholder="请输入Hash键"
                  @keydown.enter.prevent/>
            </n-form-item>
            <n-form-item
                :label="`值${index+1}`"
                :rule="emptyRule"
                :path="`data[${index}].value`">
              <n-input
                  v-model:value="form.data[index].value"
                  placeholder="请输入值"
                  @keydown.enter.prevent/>
            </n-form-item>
          </n-dynamic-input>
        </div>
        <div v-else>
          <n-dynamic-input
              v-model:value="form.data"
              :on-create="onCreate"
              :min="1"
              #="{ index }">
            <n-form-item
                class="w-full"
                :label="`值${index+1}`"
                :rule="emptyRule"
                :path="`data[${index}].value`">
              <n-input
                  v-model:value="form.data[index].value"
                  placeholder="请输入值"
                  @keydown.enter.prevent/>
            </n-form-item>
          </n-dynamic-input>
        </div>
        <n-button type="success" block size="large"
                  @click="handleSubmit">提交
        </n-button>
      </n-form>
    </div>
  </n-modal>
</template>

<script setup lang="ts">
import {ref} from "vue";
import api from "@/api";

import {useRoute} from "vue-router";
import dayjs from "@/utils/time";
import {useDatabaseStore} from "@/store";
import {debounce} from "@/utils";

const databaseStore = useDatabaseStore()
const emits = defineEmits(['onSubmit'])
const route = useRoute()
const tab = ref('string')
const canSwitch = ref(true)
const mode = ref('create')
const keyInputLoading = ref(false)
const hasKey = ref(false)

const form = ref({
  key: '',
  expire: '',
  data: [{
    hashKey: '',
    score: '',
    value: ''
  }],
})
const formRef = ref()
const emptyRule = ref({
  trigger: ['input', 'blur'],
  required: true,
  message: '请输入',
})
const rules = ref({
  key: [{
    required: true,
    message: '请输入键',
    trigger: ['input']
  }],
  score: [{
    required: true,
    message: '请输入分值',
    trigger: ['input']
  }],
  hashKey: [{
    required: true,
    message: '请输入哈希键',
    trigger: ['input']
  }],

})
const show = ref(false)
const tabUpdate = (e: any) => {
  tab.value = e
}
const tabBeforeLeave = () => {
  if (!canSwitch.value) {
    window.$message.warning("不可变换键类型")
  }
  return canSwitch.value
}
const onKeyInput = debounce(() => {
  keyInputLoading.value = true
  hasKey.value = false

  api.redis.hasKey({
    name: route.params.key,
    index: route.params.index,
    key: form.value.key
  }).then(res => {
    if (res.data.code === 0) {
      if (res.data.msg === '该键已存在') {
        hasKey.value = true
      }
    } else {
      databaseStore.errorDb(route.params.key)
    }
  }).finally(() => {
    keyInputLoading.value = false
  })
}, 500)
const onCreate = () => {
  return {
    hashKey: '',
    score: '',
    value: '',
  }
}

const handleSubmit = () => {
  formRef.value.validate((error: any) => {
    if (!error) {
      if (hasKey.value) {
        window.$dialog.warning({
          title: '该键已存在',
          content: '继续提交会覆盖原数据，是否继续？',
          positiveText: '继续',
          negativeText: '取消',
          onPositiveClick: () => {
            submit()
          }
        })
      } else {
        submit()
      }
    }
  })
}

const submit = () => {
  api.redis.addKey({
    name: route.params.key,
    index: route.params.index,
    ...form.value,
    type: tab.value,
  }).then(res => {
    if (res.data.code === 0) {
      window.$message.success(res.data.msg)
      emits('onSubmit')
      doHide()
    } else {
      databaseStore.errorDb(route.params.key)
      doHide()
    }
  })
}

const modalClose = () => {
  mode.value = 'create'
  hasKey.value = false
  tab.value = 'string'
  form.value = {
    key: '',
    expire: '',
    data: [{
      hashKey: '',
      score: '',
      value: ''
    }],
  }
}
const doParamsShow = (params: any) => {
  canSwitch.value = false
  show.value = true
  mode.value = 'edit'
  tab.value = params.type
  form.value = JSON.parse(JSON.stringify(params))
  if (form.value.expire.toString() !== '-1') {
    form.value.expire = dayjs.unix(Number(params.expire)).diff(dayjs(), 'second').toString()
  } else {
    form.value.expire = ''
  }
  if (params.type === 'hash' || params.type === 'list' || params.type === 'string' || params.type === 'set') {
    form.value.data = []
    const keys = Object.keys(params.data);
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      form.value.data.push({
        hashKey: key,
        score: key,
        value: params.data[key],
      })
    }
  } else if (params.type === 'zset') {
    form.value.data = []
    const keys = Object.keys(params.data);
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      form.value.data.push({
        hashKey: key,
        score: params.data[key].score,
        value: params.data[key].value,
      })
    }
  }
}
const doShow = () => {
  mode.value = 'create'
  canSwitch.value = true
  show.value = true
}
const doHide = () => {
  show.value = false
}
defineExpose({
  doShow,
  doHide,
  doParamsShow
})

</script>

<style scoped>

</style>